package com.wh.sse.controller;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.wh.common.service.NoticeService;
import com.wh.sse.service.SseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;


/**
 * @author 1
 * @since 2024-06-24 星期一 12:37:44
 */
@Slf4j
@RestController
@RequestMapping("/sse")
public class SseController {

    @Autowired
    private SseService sseService;

    @Autowired
    private NoticeService noticeService;


    // 保存所有活跃的 SseEmitter 实例
    private final List<SseEmitter> emitters = new CopyOnWriteArrayList<>();

    // 保存用户 ID 和对应的 SseEmitter 实例列表的映射
    private final Map<Long, List<SseEmitter>> userEmitters = new ConcurrentHashMap<>();

    // 保存用户 ID 和对应的未读消息的映射
    private final Map<Long, List<Map<String, String>>> userUnreadMessages = new ConcurrentHashMap<>();

    private final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * SSE 连接端点，客户端连接到这个端点以接收服务器推送的事件
     *
     * @param userId 用户 ID
     * @return SseEmitter 实例
     */
    @GetMapping(value = "/store/{userId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sse(@PathVariable("userId") Long userId) {


        // 创建新的 SseEmitter 实例
        SseEmitter sseEmitter = new SseEmitter(0L);
        // 添加到活跃列表
        emitters.add(sseEmitter);

        // 将用户 ID 和 SseEmitter 的映射保存
        userEmitters.computeIfAbsent(userId, k -> new CopyOnWriteArrayList<>()).add(sseEmitter);

        // 设置 SseEmitter 的各种回调，以便在完成、超时或发生错误时进行处理
        sseEmitter.onCompletion(() -> {
            emitters.remove(sseEmitter);
            userEmitters.get(userId).remove(sseEmitter);
        });
        sseEmitter.onTimeout(() -> {
            sseEmitter.complete();
            emitters.remove(sseEmitter);
            userEmitters.get(userId).remove(sseEmitter);
        });
        sseEmitter.onError(e -> {
            emitters.remove(sseEmitter);
            userEmitters.get(userId).remove(sseEmitter);
        });
        // 发送最新公告和未读消息
        try {
            // 发送最新公告
            String latestAnnouncement = getLatestAnnouncement();
            Map<String, String> announcementMessage = new HashMap<>();
            announcementMessage.put("type", "announcement");
            announcementMessage.put("content", latestAnnouncement);
            sseEmitter.send(SseEmitter.event().data(objectMapper.writeValueAsString(announcementMessage)));
            // 发送未读消息
            List<Map<String, String>> unreadMessages = userUnreadMessages.get(userId);
            if (unreadMessages != null) {
                for (Map<String, String> message : unreadMessages) {
                    sseEmitter.send(SseEmitter.event().data(objectMapper.writeValueAsString(message)));
                }
                userUnreadMessages.remove(userId);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return sseEmitter;
    }
    /**
     * 发送公告消息给所有活跃的客户端
     *
     * @param noticeText 公告内容
     */
    public void sendAnnouncement(String noticeText) {
        Map<String, String> message = new HashMap<>();
        message.put("type", "announcement");
        message.put("content", noticeText);
        for (SseEmitter emitter : emitters) {
            try {

                emitter.send(SseEmitter.event().data(objectMapper.writeValueAsString(message)));
            } catch (IOException e) {
                emitters.remove(emitter);
            }
        }
    }
    /**
     * 向指定用户发送消息
     *
     * @param userId 用户 ID
     * @param message 消息内容
     */
    public void sendAppointMessage(Long userId, String message) {
        List<SseEmitter> emitters = userEmitters.get(userId);
        if (emitters != null && !emitters.isEmpty()) {
            Map<String, String> msg = new HashMap<>();
            msg.put("type", "order");
            msg.put("content", message);
            for (SseEmitter emitter : emitters) {
                try {
                    emitter.send(SseEmitter.event().data(objectMapper.writeValueAsString(msg)));
                } catch (IOException e) {
                    emitters.remove(emitter);
                }
            }
        } else {
            storeUnreadMessage(userId, message, "order");
        }
    }
    /**
     * 存储未读消息
     *
     * @param userId 用户 ID
     * @param message 消息内容
     * @param messageType 消息类型
     */
    private void storeUnreadMessage(Long userId, String message, String messageType) {
        List<Map<String, String>> userMessages = userUnreadMessages.computeIfAbsent(userId, k -> new CopyOnWriteArrayList<>());
        Map<String, String> msg = new HashMap<>();
        msg.put("type", messageType);
        msg.put("content", message);
        userMessages.add(msg);
    }

    /**
     * 获取最新公告
     *
     * @return 最新公告内容
     */
    private String getLatestAnnouncement() {
        // 返回最新的公告内容
        return noticeService.getTopData();
    }
}